package com.allwees.support.fileservice.upload;

import com.allwees.core.common.util.UuidUtil;
import com.allwees.support.fileservice.config.FileConfig;
import com.allwees.support.fileservice.fileinfo.dao.FileInfoDao;
import com.allwees.support.fileservice.fileinfo.entity.FileInfo;
import com.allwees.support.fileservice.model.FileOwner;
import com.allwees.support.fileservice.model.FileSummary;
import com.allwees.support.fileservice.model.PutFileResult;
import com.allwees.support.fileservice.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;

@Slf4j
public class UploadFileUtil {
	private static FileConfig config;

	private static FileInfoDao fileInfoDao;

	public void init(FileConfig config, FileInfoDao fileInfoDao) {
		UploadFileUtil.config = config;
		UploadFileUtil.fileInfoDao = fileInfoDao;
	}

	/**
	 * 上传系统文件(文件bucket应属于参数<code>file.sysBuckets</code>配置的组)
	 *
	 * @param fileInfo
	 * @param bucketInfo
	 * @return
	 */
	public static FileSummary uploadSysFile(UploadFileInfo fileInfo, BucketInfo bucketInfo) {
		config.check4SysBucket(bucketInfo.getBucket());
		return uploadFile(fileInfo, bucketInfo, null);
	}

	/**
	 * 上传业务文件(文件bucket应属于参数<code>file.bsBuckets</code>配置的组)
	 *
	 * @param fileInfo
	 * @param bucketInfo
	 * @return
	 */
	public static FileSummary uploadBsFile(UploadFileInfo fileInfo, BucketInfo bucketInfo) {
		return uploadBsFile(fileInfo, bucketInfo, null);
	}

	/**
	 * 上传业务文件(文件bucket应属于参数<code>file.bsBuckets</code>配置的组)
	 *
	 * @param fileInfo
	 * @param bucketInfo
	 * @param userId
	 * @return
	 */
	public static FileSummary uploadBsFile(UploadFileInfo fileInfo, BucketInfo bucketInfo, String userId) {
		config.check4BsBucket(bucketInfo.getBucket());
		return uploadFile(fileInfo, bucketInfo, userId);
	}

	/**
	 * 上传临时文件(文件bucket应属于参数<code>file.tempBuckets</code>配置的组)
	 *
	 * @param fileInfo
	 * @return
	 */
	public static FileSummary uploadTempFile(UploadFileInfo fileInfo) {
		AliossBucketEnum bucketEnum = AliossBucketEnum.getEnum(config.getTempBucket());
		BucketInfo bucketInfo = new BucketInfo(getRealBucket(bucketEnum.getBucket()), "temp", false);
		return uploadFile(fileInfo, bucketInfo, null);
	}

	/**
	 * 上传用户文件
	 *
	 * @param fileInfo
	 * @return
	 */
	public static FileSummary uploadUserFile(UploadFileInfo fileInfo, BucketInfo bucketInfo) {
		//bucketInfo.setDir(concat(bucketInfo.getDir(), userId));
		return uploadFile(fileInfo, bucketInfo, "");
	}

	/**
	 * 上传文件，返回文件摘要信息
	 *
	 * @param uploadFileInfo - 文件内容
	 * @param bucketInfo     - 文件容器信息
	 * @param userId         - 文件所有者
	 * @return 文件摘要信息
	 */
	private static FileSummary uploadFile(UploadFileInfo uploadFileInfo, BucketInfo bucketInfo, String userId) {
		String fileName = uploadFileInfo.getFileName();
		String key = StringUtils.isBlank(userId) ? fileName : userId + "/" + fileName;

		//先上传major FileService
		FileService majorFileService = FileService.findMajorFileService();
		FileSummary fileSummary = uploadFile(uploadFileInfo, bucketInfo, userId, key, majorFileService);
		log.info("upload file[{}/{}] successfully", bucketInfo.getBucket(), key);
		return fileSummary;
	}

	private static FileSummary uploadFile(UploadFileInfo uploadFileInfo, BucketInfo bucketInfo, String userId, String key, FileService fileService) {

		String bucket = getRealBucket(bucketInfo.getBucket());
		key = concat(bucketInfo.getDir(), fileService.genFileKey(key));

		byte[] content = uploadFileInfo.getBytes();

		PutFileResult result = fileService.putFile(bucket, key, content);
		String url = getRealAccess(fileService, bucket) + "/" + key;
		FileSummary summary = new FileSummary();
		summary.setBucketName(bucket);
		summary.setKey(key);
		summary.setETag(result.getETag());
		summary.setOwner(userId == null ? null : new FileOwner(userId));
		summary.setSize(content.length);
		summary.setLastModified(new Date());
		summary.setStorageClass(uploadFileInfo.getSuffix());
		summary.setRelativePath(key);
		summary.setUrl(url);

		//临时文件不保存FileInfo
		if(!config.isTempBucket(bucket)) {
			//保存文件Metadata
			FileInfo fileInfo = new FileInfo();
			fileInfo.setOriginalName(uploadFileInfo.getOriginalName());
			fileInfo.setDescription(uploadFileInfo.getDescription());
			fileInfo.setSize(content.length);
			fileInfo.setSuffix(uploadFileInfo.getSuffix());
			fileInfo.setBucket(bucket);
			fileInfo.setRelativePath(key);
			fileInfo.setUrl(url);
			fileInfo.setUuid(UuidUtil.generate());
			fileInfo.setType(fileService.getType());
			fileInfo.setCreateAt(new Date());
			fileInfoDao.save(fileInfo);
		}
		return summary;
	}

	/**
	 * 获取真实的bucket
	 * @param bucket
	 * @return
	 */
	public static String getRealBucket(String bucket){
		return config.getRealBucket(bucket);
	}

	/**
	 * 获取实际的endpoint（主要针对阿里云OSS强制根据bucket使用三级域名的情况）
	 *
	 * @param fileService
	 * @param bucket
	 * @return
	 */
	private static String getRealAccess(FileService fileService, String bucket) {
		String accessPrefix = fileService.getAccessPrefix();
		if("alioss".equals(fileService.getType())) {
			if (accessPrefix.contains("BUCKET")){
				accessPrefix = accessPrefix.replace("BUCKET", bucket);
			}
			return accessPrefix;
		} else {
			return accessPrefix + "/" + bucket;
		}
	}

	private static String concat(String... strs) {
		if(ArrayUtils.isEmpty(strs)){
			return StringUtils.EMPTY;
		}
		String str = "";
        for (String s : strs) {
            if (StringUtils.isBlank(s)) {
                continue;
            }
            if (StringUtils.isBlank(str)) {
                str = s;
                continue;
            }
            if (str.endsWith("/") || s.startsWith("/")) {
                str += s;
            } else {
                str += "/" + s;
            }
        }
		return str;
	}
}
